package com.africanmoviesmobile.ui;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Vector;

import org.pixmob.httpclient.HttpClientException;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.africanmoviesmobile.R;
import com.africanmoviesmobile.util.bitmap.ImageCache.ImageCacheParams;
import com.africanmoviesmobile.util.bitmap.ImageFetcher;
import com.africanmoviesmobile.webservice.AmmWebService;
import com.africanmoviesmobile.webservice.BasicAsyncCallback;
import com.africanmoviesmobile.webservice.WebServiceException;
import com.africanmoviesmobile.webservice.inf.User;
import com.africanmoviesmobile.webservice.inf.WebserviceObject;
import com.africanmoviesmobile.webservice.inf.Wishlist;

public class WishlistActivity extends BaseActivity implements OnItemClickListener, OnScrollListener {
	
	private LayoutInflater mLayoutInflater;
	private ListView mWishlistListView;
	private LinearLayout mLoadingProgress;
	private LinearLayout mEmptyWishlist;
	
	private ImageFetcher mThumbnailImageFetcher;
	
	AmmWebService mAmmWebService;
	User mUser = null;
	
	private WishlistAdapter mWishlistAdapter;
	
	private boolean mLastItemVisible = false;
    private boolean mLoadingInProgress = false;
	private int mResultPage;
	private int mPageCount;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		setContentView(R.layout.wishlist_activity);
		
		int thumbnailWidth = getResources().getDimensionPixelSize(R.dimen.thumbnail_width);
		int thumbnailHeight = getResources().getDimensionPixelSize(R.dimen.thumbnail_height);
		mThumbnailImageFetcher = new ImageFetcher(this, thumbnailWidth, thumbnailHeight);
		mThumbnailImageFetcher.setLoadingImage(R.drawable.empty_photo);
		mThumbnailImageFetcher.addImageCache(getSupportFragmentManager(), new ImageCacheParams(this, CACHE_DIR_THUMBNAIL));
		
		mWishlistAdapter = new WishlistAdapter();
		
		mLayoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		mLoadingProgress = (LinearLayout) mLayoutInflater.inflate(R.layout.loading_progress_small, null);
    	
		mEmptyWishlist = (LinearLayout) findViewById(R.id.empty_wishlist);
		
		mWishlistListView = (ListView) findViewById(R.id.list);
		mWishlistListView.setDividerHeight(0);
		mWishlistListView.addHeaderView(mLoadingProgress);
		mWishlistListView.setAdapter(mWishlistAdapter);
		mWishlistListView.setOnItemClickListener(this);
		mWishlistListView.setOnScrollListener(this);
		
		registerForContextMenu(mWishlistListView);
		
		mResultPage = 1;
		mAmmWebService = AmmWebService.getInstance(this);
		
		mAmmWebService.getUser(getLoginEmail(), new BasicAsyncCallback() {

			public void onComplete(final WebserviceObject[] result, final Object state) {

				User user = (User) result[0];
				
				if(user != null){
					
					mUser = user;
					
					Hashtable<String, String> params = new Hashtable<String, String>();
					params.put("page", Integer.toString(mResultPage));
					
					Wishlist[] userWishlist = null;
					
					try {
						userWishlist = mUser.getWishlist(params);
					} catch (HttpClientException e) {
						Log.w("AMM HttpClientException:", e.getMessage());
					} catch (IOException e) {
						Log.w("AMM IOException:", e.getMessage());
					} catch (WebServiceException e) {
						Log.w("AMM WebServiceException:", e.getMessage());
						toastMessage(e.getMessage());
					}
					
					if ((userWishlist != null) && (userWishlist.length > 0)) {
		
						mPageCount = mUser.getResultPageCount();
						
						runOnUiThread(new Runnable() {public void run() { mWishlistListView.removeHeaderView(mLoadingProgress); }});
						
						for (int i = 0; i < userWishlist.length; i++) {
							final Wishlist wishlist = (Wishlist) userWishlist[i];
							runOnUiThread(new Runnable() {public void run() { mWishlistAdapter.add(wishlist); }});	
						}
						
					}else{
						runOnUiThread(new Runnable() {
							public void run() {
								mWishlistListView.removeHeaderView(mLoadingProgress);
								mEmptyWishlist.setVisibility(View.VISIBLE);
							}
						});
					}	
				}
			}

			public void onHttpClientException(final HttpClientException e, final Object state) {
				Log.w("AMM HttpClientException:", e.getMessage());
			}
			
			public void onIOException(final IOException e, final Object state) {
				Log.w("AMM IOException:", e.getMessage());
			}

			public void onWebServiceException(final WebServiceException e, final Object state) {
				Log.w("AMM WebServiceException:", e.getMessage());
				toastMessage(R.string.user_info_error);
			}

		}, null);
		
	}
	
	@Override
    public void onResume() {
        super.onResume();
        mThumbnailImageFetcher.setExitTasksEarly(false);
        mWishlistAdapter.notifyDataSetChanged();
    }

    @Override
    public void onPause() {
        super.onPause();
        mThumbnailImageFetcher.setPauseWork(false);
        mThumbnailImageFetcher.setExitTasksEarly(true);
        mThumbnailImageFetcher.flushCache();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mThumbnailImageFetcher.closeCache();
    }
	
    @Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    	final Intent intent = new Intent(this, MovieDetailActivity.class);
		intent.putExtra(MovieDetailActivity.EXTRA_MOVIE_ID, (int) id);
        startActivity(intent);
	}
    
    @Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		mLastItemVisible = (totalItemCount > 0) && (firstVisibleItem + visibleItemCount >= totalItemCount - 1);
	}
    
    @Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		/**
		 * Check that the scrolling has stopped, and that the last item is
		 * visible.
		 */
		if ((scrollState == OnScrollListener.SCROLL_STATE_IDLE) && mLastItemVisible) {

			//check if we still have more page left and we aren't loading any data
			if ((mResultPage < mPageCount) && (!mLoadingInProgress)) {
				mWishlistListView.addFooterView(mLoadingProgress);
				mResultPage++;
				loadMoreWishlist();
				mLastItemVisible = false;
				mLoadingInProgress = true;
			}
			
		}
		
		// Pause fetcher to ensure smoother scrolling when flinging
        if (scrollState == OnScrollListener.SCROLL_STATE_FLING) {
            mThumbnailImageFetcher.setPauseWork(true);
        } else {
            mThumbnailImageFetcher.setPauseWork(false);
        }
	}
    
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add(Menu.NONE, R.id.context_menu_preview, Menu.NONE, R.string.preview);
        menu.add(Menu.NONE, R.id.context_menu_play, Menu.NONE, R.string.play);
        menu.add(Menu.NONE, R.id.context_menu_playlist, Menu.NONE, R.string.add_to_playlist);
        menu.add(Menu.NONE, R.id.context_menu_remove_wishlist, Menu.NONE, R.string.remove_from_wishlist);
    }
    
    @Override
    public boolean onContextItemSelected(MenuItem item) {
		 AdapterContextMenuInfo contextMenuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
        switch (item.getItemId()) {
	        case R.id.context_menu_preview:
	            playMovie((int) contextMenuInfo.id, R.string.preview);
	            return true;
	        case R.id.context_menu_play:
	            playMovie((int) contextMenuInfo.id, R.string.play);
	            return true;
            case R.id.context_menu_playlist:
           	 	addPlaylist((int) contextMenuInfo.id, null);
                return true;    
            case R.id.context_menu_remove_wishlist:
            	mWishlistAdapter.delete(contextMenuInfo.position);
                return true;       
        }
        return super.onContextItemSelected(item);
    }
    
    private void loadMoreWishlist() {
    
    	Hashtable<String, String> params = new Hashtable<String, String>();
		params.put("page", Integer.toString(mResultPage));

		mUser.getWishlist(params, new BasicAsyncCallback() {

		public void onComplete(final WebserviceObject[] result, final Object state) {

			runOnUiThread(new Runnable() {public void run() { mWishlistListView.removeFooterView(mLoadingProgress); }});
			
			mLoadingInProgress = false;
			
			Wishlist[] userWishlist = (Wishlist[]) result;

			if ((userWishlist != null)) {
																	
				for (int i = 0; i < userWishlist.length; i++) {
					
					final Wishlist wishlist = (Wishlist) (userWishlist[i]);
					
					runOnUiThread(new Runnable() {public void run() { mWishlistAdapter.add(wishlist); }});
					
				}
			} 
		}

		public void onHttpClientException(final HttpClientException e, final Object state) {
			mLoadingInProgress = false;
			runOnUiThread(new Runnable() {public void run() { mWishlistListView.removeFooterView(mLoadingProgress); }});
			Log.w("AMM HttpClientException:", e.getMessage());
		}
		
		public void onIOException(final IOException e, final Object state) {
			mLoadingInProgress = false;
			runOnUiThread(new Runnable() {public void run() { mWishlistListView.removeFooterView(mLoadingProgress); }});
			Log.w("AMM IOException:", e.getMessage());
		}

		public void onWebServiceException(final WebServiceException e, final Object state) {
			mLoadingInProgress = false;
			runOnUiThread(new Runnable() {public void run() { mWishlistListView.removeFooterView(mLoadingProgress); }});
			Log.w("AMM WebServiceException:", e.getMessage());
			toastMessage(e.getMessage());
		}

	}, null);
    	
    }
    
	public class WishlistAdapter extends BaseAdapter {

		private static final int VIEW_TYPE_LIST_WISHLIST = 0;
		private static final int VIEW_TYPE_DELETING_WISHLIST = 1;
		
		private Vector<Wishlist> mListElements = new Vector<Wishlist>();
		private ArrayList<Integer> mDeleteInProgressList = new ArrayList<Integer>();
		
		private class ViewHolder {
			public TextView mMovieTitle;
			public TextView mMovieCast;
    	    public ImageView mMovieCover;
    	    public ImageView mMovieRating;
    	    public TextView mLoadingProgressText;
    	}
		
        public WishlistAdapter() {
        }

        public int getCount() {
        	if (mListElements.isEmpty()) {
    			return 0;
    		} else {
    			return mListElements.size();
    		}
        }

        public Object getItem(int position) {
        	Wishlist wishlist = (Wishlist) mListElements.elementAt(position);
        	return wishlist;
        }

        public long getItemId(int position) {
        	Wishlist wishlist = (Wishlist) mListElements.elementAt(position);
    		return wishlist.getMovieId();
        }
        
        public int getItemViewType(int position) {
        	if(mDeleteInProgressList.contains(Integer.valueOf(position))){
        		return VIEW_TYPE_DELETING_WISHLIST;
        	}else{
        		return VIEW_TYPE_LIST_WISHLIST;
        	}
        }

        public int getViewTypeCount() {
            return 2;
        }

        public View getView(int position, View convertView, ViewGroup parent) {

        	Wishlist wishlist = (Wishlist) mListElements.elementAt(position);
        	
        	ViewHolder holder;
        	
        	View wishlistRow = convertView;
        	
        	if(wishlistRow == null){
        		
        		holder  = new ViewHolder();
        		
        		if(getItemViewType(position) == VIEW_TYPE_LIST_WISHLIST){
        			wishlistRow = mLayoutInflater.inflate(R.layout.movie_listview_row, parent, false);
            		holder.mMovieTitle = (TextView) wishlistRow.findViewById(R.id.movie_title);
            		holder.mMovieCast = (TextView) wishlistRow.findViewById(R.id.movie_cast);
            		holder.mMovieRating = (ImageView) wishlistRow.findViewById(R.id.movie_rating);
            		holder.mMovieCover = (ImageView) wishlistRow.findViewById(R.id.movie_cover);
        		}else{
        			wishlistRow = mLayoutInflater.inflate(R.layout.loading_progress_small, parent, false);
            		holder.mLoadingProgressText = (TextView) wishlistRow.findViewById(R.id.loading_progress_text);
            		holder.mLoadingProgressText.setText(R.string.removing_title);
        		}
        		
        		wishlistRow.setTag(holder);
        	}else{
        		holder = (ViewHolder) wishlistRow.getTag();
        	}
        	
        	if(getItemViewType(position) == VIEW_TYPE_LIST_WISHLIST){
        		holder.mMovieTitle.setText(wishlist.getMovieTitle());
            	holder.mMovieCast.setText(wishlist.getMovieShortCast());
            	holder.mMovieRating.setImageResource(mRatingsStarDarkArray[wishlist.getMovieRatings()]);
            	mThumbnailImageFetcher.loadImage(wishlist.getMovieCover(), holder.mMovieCover);
        	}
     
        	return wishlistRow;
        }
   
        public void delete(final int position) {
        	
        	mDeleteInProgressList.add(Integer.valueOf(position));
        	notifyDataSetChanged();
        	
        	Wishlist wishlist = (Wishlist) mListElements.elementAt(position);
        	
        	mUser.deleteWishlist(wishlist.getMovieId(), new BasicAsyncCallback() {

				public void onComplete(final boolean[] result, final Object state) {
												
					boolean response = (boolean) result[0];
										
					if (response == true) {
						
						runOnUiThread(new Runnable() {public void run() { 
							
							mDeleteInProgressList.remove(Integer.valueOf(position));
							mListElements.removeElementAt(position);
				            notifyDataSetChanged();

							toastMessage(R.string.wishlist_removed_toast);
							
				            if(getCount() <= 0){
				            	mEmptyWishlist.setVisibility(View.VISIBLE);
				            }
				            
						}});
						
					} else {
						runOnUiThread(new Runnable() {public void run() { 
							mDeleteInProgressList.remove(Integer.valueOf(position));
				            notifyDataSetChanged();
						}});
						toastMessage(R.string.wishlist_removing_error_toast);
					}
					
				}
		
				public void onHttpClientException(final HttpClientException e, final Object state) {
					Log.w("AMM HttpClientException:", e.getMessage());
					runOnUiThread(new Runnable() {public void run() { 
						mDeleteInProgressList.remove(Integer.valueOf(position));
			            notifyDataSetChanged();
					}});
				}
				
				public void onIOException(final IOException e, final Object state) {
					Log.w("AMM IOException:", e.getMessage());
					runOnUiThread(new Runnable() {public void run() { 
						mDeleteInProgressList.remove(Integer.valueOf(position));
			            notifyDataSetChanged();
					}});
				}
		
				public void onWebServiceException(final WebServiceException e, final Object state) {
					Log.w("AMM WebServiceException:", e.getMessage());
					runOnUiThread(new Runnable() {public void run() { 
						mDeleteInProgressList.remove(Integer.valueOf(position));
			            notifyDataSetChanged();
					}});
					toastMessage(e.getMessage());
				}
		
			}, null);
        	
        }
        
        public void add(Wishlist data) {
        	mListElements.addElement(data);
            notifyDataSetChanged();
        }

    }
	
}
